package cn.toma.service.impl.sys;

import cn.toma.common.utils.Tree;
import cn.toma.common.utils.TreeUtil;
import cn.toma.common.vo.FfBootConstant;
import cn.toma.core.AbstractService;
import cn.toma.dao.sys.MenuMapper;
import cn.toma.dto.MenuTree;
import cn.toma.manager.sys.UserManager;
import cn.toma.model.sys.Menu;
import cn.toma.service.sys.MenuService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.weekend.Weekend;
import tk.mybatis.mapper.weekend.WeekendCriteria;

import javax.annotation.Resource;
import java.util.*;

@Slf4j
@Service("menuService")
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class MenuServiceImpl extends AbstractService<Menu> implements MenuService
{


	@Resource
	private MenuMapper menuMapper;

	@Override
	public List<Menu> findUserPermissions(String username)
	{
		return this.menuMapper.findUserPermissions(username);
	}

	@Override
	public List<Menu> findUserMenus(String username)
	{
		return this.menuMapper.findUserMenus(username);
	}

	@Override
	public Map<String, Object> findMenus(Menu menu)
	{
		Map<String, Object> result = new HashMap<>();
		try {

			List<Menu> menus = menuMapper.select(menu);
			List<Tree<Menu>> trees = new ArrayList<>();
			buildTrees(trees, menus);
			if (StringUtils.equals(menu.getType(), FfBootConstant.TYPE_BUTTON)) {
				result.put("rows", trees);
			}
			else {
				List<? extends Tree> menuTree = TreeUtil.build(trees);
				result.put("rows", menuTree);
			}

			result.put("total", menus.size());
		} catch (NumberFormatException e) {
			log.error("查询菜单失败", e);
			result.put("rows", null);
			result.put("total", 0);
		}
		return result;
	}


	@Override
	public List<Menu> findMenuList(Menu menu)
	{
		List<Menu> menuList = findMenuCondition(menu);

		return menuList;
	}

	@Override
	@Transactional
	public void createMenu(Menu menu)
	{
		menu.setCreateTime(new Date());
		setMenu(menu);
		this.save(menu);
	}

	@Override
	@Transactional
	public void updateMenu(Menu menu) throws Exception
	{
		menu.setModifyTime(new Date());
		setMenu(menu);
		this.menuMapper.updateByPrimaryKeySelective(menu);
	}

	@Override
	@Transactional
	public void deleteMeuns(String[] menuIds) throws Exception
	{
		for (String menuId : menuIds) {
			// 递归删除这些菜单/按钮
			this.menuMapper.deleteMenus(menuId);
		}
	}

	private void buildTrees(List<Tree<Menu>> trees, List<Menu> menus)
	{
		menus.forEach(menu ->
		{
			MenuTree tree = new MenuTree();
			tree.setId(menu.getMenuId().toString());
			tree.setParentId(menu.getParentId().toString());
			tree.setLabel(menu.getMenuName());
			tree.setComponent(menu.getComponent());
			tree.setIcon(menu.getIcon());
			tree.setOrderNum(menu.getOrderNum() == null ? 0 : menu.getOrderNum().intValue());
			tree.setPath(menu.getPath());
			tree.setType(menu.getType());
			tree.setPerms(menu.getPerms());
			trees.add(tree);
		});
	}

	private void setMenu(Menu menu)
	{
		if (menu.getParentId() == null) {
			menu.setParentId(0L);
		}
		if (Menu.TYPE_BUTTON.equals(menu.getType())) {
			menu.setPath(null);
			menu.setIcon(null);
			menu.setComponent(null);
		}
	}

	private List<Menu> findMenuCondition(Menu menu)
	{

		Weekend<Menu> weekend = new Weekend<>(Menu.class);
		WeekendCriteria<Menu, Object> weekendCriteria = weekend.weekendCriteria();
		weekend.orderBy("menuId").asc();
		if (StringUtils.isNotBlank(menu.getMenuName())) {
			weekendCriteria.andEqualTo(Menu::getMenuName, menu.getMenuName());
		}
		if (StringUtils.isNotBlank(menu.getType())) {
			weekendCriteria.andEqualTo(Menu::getType, menu.getType());
		}
		if (StringUtils.isNotBlank(menu.getCreateTimeFrom()) && StringUtils.isNotBlank(menu.getCreateTimeTo())) {
			weekendCriteria.andGreaterThanOrEqualTo
					(Menu::getCreateTime, menu.getCreateTimeFrom())
					.andLessThanOrEqualTo(Menu::getCreateTime, menu.getCreateTimeTo());
		}

		List<Menu> menus = this.menuMapper.selectByCondition(weekend);
		return menus;
	}

}
